


#ifndef PF_SOLID_H
#define PF_SOLID_H

#include "pf_atomicentity.h"
#include "pf_vector.h"
#include "lx_Export.h"

/**
 * Holds the data that defines a solid.
 */
class LX_EXPORT PF_SolidAttribute {
public:
    /**
     * Default constructor. Leaves the data object uninitialized.
     */
    PF_SolidAttribute() {
        for (int i=0; i<4; ++i) {
            corner[i] = PF_Vector(false);
        }
    }

    /**
     * Constructor for a solid with 3 corners.
     */
    PF_SolidAttribute(const PF_Vector& corner1,
                 const PF_Vector& corner2,
                 const PF_Vector& corner3) {

        corner[0] = corner1;
        corner[1] = corner2;
        corner[2] = corner3;
        corner[3] = PF_Vector(false);
    }

    /**
     * Constructor for a solid with 4 corners.
     */
    PF_SolidAttribute(const PF_Vector& corner1,
                 const PF_Vector& corner2,
                 const PF_Vector& corner3,
                 const PF_Vector& corner4) {

        corner[0] = corner1;
        corner[1] = corner2;
        corner[2] = corner3;
        corner[3] = corner4;
    }

    friend class PF_Solid;

    friend std::ostream& operator << (std::ostream& os,
                                      const PF_SolidAttribute& pd) {
        os << "(";
        for (int i=0; i<4; i++) {
            os << pd.corner[i];
        }
        os << ")";
        return os;
    }

private:
    PF_Vector corner[4];
};



/**
 * Class for a solid entity (e.g. dimension arrows).
 *

 */
class LX_EXPORT PF_Solid : public PF_AtomicEntity {
public:
    PF_Solid(PF_Container* parent,
             const PF_SolidAttribute& d);

    virtual PF_Entity* clone() {
        PF_Solid* s = new PF_Solid(*this);
        s->initId();
        return s;
    }

    /**	@return PF_ENTITY_POINT */
    virtual LX_Define::EntityType rtti() const {
        return LX_Define::EntitySolid;
    }
	
    /** 
	 * @return Start point of the entity. 
	 */
    virtual PF_Vector getStartpoint() const {
        return PF_Vector(false);
    }
    /** 
	 * @return End point of the entity. 
	 */
    virtual PF_Vector getEndpoint() const {
        return PF_Vector(false);
    }


    /** @return Copy of data that defines the point. */
    PF_SolidAttribute getData() const {
        return data;
    }

    /** @return true if this is a triangle. */
    bool isTriangle() {
        return !data.corner[3].valid;
    }

    PF_Vector getCorner(int num);

    void shapeArrow(const PF_Vector& point,
                    double angle,
                    double arrowSize);

    virtual PF_Vector getNearestEndpoint(const PF_Vector& coord,
                                         double* dist = NULL);
    virtual PF_Vector getNearestPointOnEntity(const PF_Vector& coord,
            bool onEntity = true, double* dist = NULL, PF_Entity** entity = NULL);
    virtual PF_Vector getNearestCenter(const PF_Vector& coord,
                                       double* dist = NULL);
    virtual PF_Vector getNearestMiddle(const PF_Vector& coord,
                                       double* dist = NULL);
    virtual PF_Vector getNearestDist(double distance,
                                     const PF_Vector& coord,
                                     double* dist = NULL);

    virtual double getDistanceToPoint(const PF_Vector& coord,
                                      PF_Entity** entity=NULL,
                                      LX_Define::ResolveLevel level=LX_Define::ResolveNone,
									  double solidDist = LX_DOUBLEMAX);

    virtual void move(PF_Vector offset);
    virtual void rotate(PF_Vector center, double angle);
    virtual void scale(PF_Vector center, PF_Vector factor);
    virtual void mirror(PF_Vector axisPoint1, PF_Vector axisPoint2);

    virtual void draw(PF_Painter* painter, PF_GraphicView* view, double patternOffset=0.0);

    friend std::ostream& operator << (std::ostream& os, const PF_Solid& p);

    /** Recalculates the borders of this entity. */
    virtual void calculateBorders ();

protected:
    PF_SolidAttribute data;
    //PF_Vector point;
}
;

#endif
